package com.wenhai.spring.bean.lifecycle;

import com.wenhai.xiaomage.spring.ioc.overview.dependency.domain.SuperUser;
import com.wenhai.xiaomage.spring.ioc.overview.dependency.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.ObjectUtils;

/**
 * @Author:wenhai
 * @Description: {@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor} Bean实例化操作
 * @Date:2020/3/16
 */
public class BeanInstantiationLifecycleDemo {
    public static void main(String[] args) {
        String[] locations = {"/META-INF/dependency-lookup-context.xml", "META-INF/constructor-dependency-context.xml"};
        ClassPathXmlApplicationContext beanFactory = new ClassPathXmlApplicationContext(locations);
        beanFactory.addBeanFactoryPostProcessor(beanFactory1-> beanFactory1.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor()));
        beanFactory.refresh();
        User user = beanFactory.getBean("user", User.class);
        User user2 = beanFactory.getBean("superUser", User.class);

        UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
        System.out.println("user  " + user);
        System.out.println("user2  " + user2);
        System.out.println("userHolder  " + userHolder);
        beanFactory.close();
    }


    static class MycAwareBeanProcessor implements InstantiationAwareBeanPostProcessor,DestructionAwareBeanPostProcessor {

        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
                return new SuperUser();
            }
            return null;
        }

        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
                User user = User.class.cast(bean);
                user.setId(1L);
                user.setUsername("文海");
                return false;
            }
            return true;
        }

        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && ObjectUtils.nullSafeEquals(bean.getClass(), UserHolder.class)) {
                MutablePropertyValues propertyValues;
                if (pvs instanceof MutablePropertyValues) {
                    propertyValues = MutablePropertyValues.class.cast(pvs);
                } else {
                    propertyValues = new MutablePropertyValues();
                }
                System.out.println(propertyValues.getPropertyValue("description").getValue());
                propertyValues.removePropertyValue("description");
                propertyValues.add("description", "The user holder V3");
                return propertyValues;
            }
            return null;
        }

        @Override
        public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
            if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
                System.out.println("postProcessBeforeDestruction方法执行");
            }
        }
    }
}
